package cn.toma.utils;

import cn.toma.common.function.CacheSelector;
import cn.toma.common.utils.EncryptUtil;
import cn.toma.common.vo.FfBootConstant;
import cn.toma.common.vo.StringPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.function.Supplier;
import java.util.stream.IntStream;

/**
 * 工具类
 */
@Slf4j
public class FfBootUtil
{

	/**
	 * 缓存查询模板
	 *
	 * @param cacheSelector    查询缓存的方法
	 * @param databaseSelector 数据库查询方法
	 * @return T
	 */
	public static <T> T selectCacheByTemplate(CacheSelector<T> cacheSelector, Supplier<T> databaseSelector)
	{
		try {
			log.debug("query data from redis ······");
			// 先查 Redis缓存
			T t = cacheSelector.select();
			if (t == null) {
				// 没有记录再查询数据库
				return databaseSelector.get();
			}
			else {
				return t;
			}
		} catch (Exception e) {
			// 缓存查询出错，则去数据库查询
			log.error("redis error：", e);
			log.debug("query data from database ······");
			return databaseSelector.get();
		}
	}

	/**
	 * token 加密
	 *
	 * @param token token
	 * @return 加密后的 token
	 */
	public static String encryptToken(String token)
	{
		try {
			EncryptUtil encryptUtil = new EncryptUtil(FfBootConstant.TOKEN_CACHE_PREFIX);
			return encryptUtil.encrypt(token);
		} catch (Exception e) {
			log.info("token加密失败：", e);
			return null;
		}
	}

	/**
	 * token 解密
	 *
	 * @param encryptToken 加密后的 token
	 * @return 解密后的 token
	 */
	public static String decryptToken(String encryptToken)
	{
		try {
			EncryptUtil encryptUtil = new EncryptUtil(FfBootConstant.TOKEN_CACHE_PREFIX);
			return encryptUtil.decrypt(encryptToken);
		} catch (Exception e) {
			log.info("token解密失败：", e);
			return null;
		}
	}

	/**
	 * 驼峰转下划线
	 *
	 * @param value 待转换值
	 * @return 结果
	 */
	public static String camelToUnderscore(String value)
	{
		if (StringUtils.isBlank(value)) {
			return value;
		}
		String[] arr = StringUtils.splitByCharacterTypeCamelCase(value);
		if (arr.length == 0) {
			return value;
		}
		StringBuilder result = new StringBuilder();
		IntStream.range(0, arr.length).forEach(i ->
		{
			if (i != arr.length - 1) {
				result.append(arr[i]).append(StringPool.UNDERSCORE);
			}
			else {
				result.append(arr[i]);
			}
		});
		return StringUtils.lowerCase(result.toString());
	}

}
